package cn.unknowpupil.init.fliter;


import cn.unknowpupil.init.common.constant.SecurityConstants;
import cn.unknowpupil.init.common.enums.ResultStatus;
import cn.unknowpupil.init.common.resopnse.ResultResponse;
import cn.unknowpupil.init.common.service.TokenService;
import cn.unknowpupil.init.domain.dto.LoginUser;
import cn.unknowpupil.init.utils.strings.MapperUtils;
import cn.unknowpupil.init.utils.security.SecurityUtils;
import cn.unknowpupil.init.utils.strings.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.security.web.util.matcher.RequestHeaderRequestMatcher;
import org.springframework.security.web.util.matcher.RequestMatcher;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.regex.Pattern;

/**
 * Created at 2020/10/19 by w10g <br>
 * Initialize JwtAuthenticationTokenFilter ... <br>
 *
 * @author unknowpupil
 * @since 0.0.1
 */
@Component
public class JwtAuthenticationTokenFilter extends OncePerRequestFilter {

    private RequestMatcher requiresAuthenticationRequestMatcher;

    public JwtAuthenticationTokenFilter() {
        this.requiresAuthenticationRequestMatcher = new RequestHeaderRequestMatcher(SecurityConstants.HEADER);
    }

    @Autowired
    private TokenService tokenService;

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        long start = System.currentTimeMillis();
       // 过滤所有的释放的url
        if (antMatchersUrls(request, response)) {
            filterChain.doFilter(request, response);
            return;
        }
        // 找出所有没带Head 的url
        if (!requiresAuthentication(request, response)) {
            filterChain.doFilter(request, response);
            return;
        }
        String requestURI = request.getRequestURI();
        System.out.println(requestURI);
        String token = tokenService.getToken(request);
        System.out.println("token: \n"+token);
        if(StringUtils.isNotBlank(token)){

            LoginUser loginUser = tokenService.getLoginUser(token);

            if (loginUser != null && SecurityUtils.getAuthentication() == null) {
               if(loginUser.isMultilateralLogin()){
                   responseResult(request,response, ResultStatus.ACCOUNT_HAS_BEEN_LOGGED);
                   tokenService.logout(loginUser.getToken());
                   return;
               }
                tokenService.verifyToken(loginUser);
                UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(loginUser, token, loginUser.getAuthorities());
                authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
                SecurityContextHolder.getContext().setAuthentication(authentication);
            }else {
                responseResult(request,response,ResultStatus.UNAUTHORIZED);
                return;
            }
        }
        System.err.println("访问---------初步耗时："+(System.currentTimeMillis()-start));
        filterChain.doFilter(request, response);

    }

    protected boolean requiresAuthentication(HttpServletRequest request,
                                             HttpServletResponse response) {
        return requiresAuthenticationRequestMatcher.matches(request);
    }

    protected boolean antMatchersUrls(HttpServletRequest request,
                                      HttpServletResponse response) {
        return AntMatchersUrlsFilter.urls.stream().filter(o -> Pattern.matches(o, request.getRequestURI())).findFirst().isPresent();
    }
    protected void responseResult(HttpServletRequest request,
                                      HttpServletResponse response,ResultStatus resultStatus) throws IOException {
        //用户信息不存在或转换错误，返回错误信息
        response.setContentType("application/json");
        response.setStatus(HttpServletResponse.SC_OK);
        response.setCharacterEncoding("UTF-8");
        response.getWriter().write(MapperUtils.obj2json(ResultResponse.buildFailure(resultStatus)));
        return;
    }


}
